// import com.alibaba.druid.DbType_ptr;
// import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor_ptr;
// import com.alibaba.druid.util.FnvHash;

// import java.sql.Types;
// import java.util.ArrayList;
// import java.util.List;

#include "SQLArrayDataType.h"
#include "expr/SQLCharExpr.h"
#include "../../utils/FnvHash.h"
#include "../../Exception/UnsupportedOperationException.h"
#include "../visitor/SQLASTVisitor.h"

SQLArrayDataType_ptr SQLArrayDataType::ARRYA_CHAR = SQLArrayDataType_ptr(new SQLArrayDataType(SQLCharExpr::DATA_TYPE));

SQLArrayDataType::SQLArrayDataType(SQLDataType_ptr componentType)
{
  setComponentType(componentType);
}

SQLArrayDataType::SQLArrayDataType(SQLDataType_ptr componentType, DbType_ptr dbType)
{
  this->dbType = dbType;
  setComponentType(componentType);
}

// @Override
string_ptr SQLArrayDataType::getName()
{
  return make_string_ptr("ARRAY");
}

// @Override
long SQLArrayDataType::nameHashCode64()
{
  return FnvHash::Constants::ARRAY;
}

// @Override
void SQLArrayDataType::setName(string_ptr name)
{
  throw new UnsupportedOperationException();
}

// @Override
SQLExpr_list_ptr SQLArrayDataType::getArguments()
{
  return arguments;
}

// @Override
BOOL_ptr SQLArrayDataType::getWithTimeZone()
{
  // return nullptr;
  return BOOL::FALSE;
}

// @Override
void SQLArrayDataType::setWithTimeZone(BOOL_ptr value)
{
  throw new UnsupportedOperationException();
}

// @Override
BOOL_ptr SQLArrayDataType::isWithLocalTimeZone()
{
  return BOOL::FALSE;
}

// @Override
void SQLArrayDataType::setWithLocalTimeZone(BOOL_ptr value)
{
  throw new UnsupportedOperationException();
}

// @Override
void SQLArrayDataType::setDbType(DbType_ptr dbType)
{
  this->dbType = dbType;
}

// @Override
DbType_ptr SQLArrayDataType::getDbType()
{
  return dbType;
}

// @Override
void SQLArrayDataType::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLArrayDataType)))
  {
    acceptChild(visitor, componentType);
  }
  visitor->endVisit(SharedObject(SQLArrayDataType));
}

SQLObject_ptr SQLArrayDataType::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLArrayDataType>(new SQLArrayDataType(std::dynamic_pointer_cast<SQLDataType>(componentType->clone())));
  std::shared_ptr<SQLArrayDataType> x = std::dynamic_pointer_cast<SQLArrayDataType>(clone_tmp);
  // SQLArrayDataType_ptr x = new SQLArrayDataType_ptr(componentType.clone());
  x->dbType = dbType;

  for (SQLExpr_ptr arg : *arguments)
  {
    SQLExpr_ptr item = std::dynamic_pointer_cast<SQLExpr>(arg->clone());
    item->setParent(x);
    x->arguments->push_back(item);
  }
  return x;
}

SQLDataType_ptr SQLArrayDataType::getComponentType()
{
  return componentType;
}

void SQLArrayDataType::setComponentType(SQLDataType_ptr x)
{
  if (x != nullptr)
  {
    x->setParent(SharedObject(SQLArrayDataType));
  }
  this->componentType = x;
}

int SQLArrayDataType::jdbcType()
{
  return Types::ARRAY;
}

// @Override
BOOL_ptr SQLArrayDataType::isInt()
{
  return BOOL::FALSE;
}

// @Override
BOOL_ptr SQLArrayDataType::isNumberic()
{
  return BOOL::FALSE;
}

// @Override
BOOL_ptr SQLArrayDataType::isString()
{
  return BOOL::FALSE;
}

// @Override
BOOL_ptr SQLArrayDataType::hasKeyLength()
{
  return BOOL::FALSE;
}
